package main

import "fmt"

func updateSlice(s []int) {
	s[0] = 100
}

func test1() {
	arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	fmt.Println("arr[2:6] =", arr[2:6])
	fmt.Println("arr[:6] =", arr[:6])
	s1 := arr[2:]
	fmt.Println("arr[2:] =", s1)
	s2 := arr[:]
	fmt.Println("arr[:] =", s2)

	fmt.Println("After updateSlice(s1)")
	updateSlice(s1)
	fmt.Println(s1)
	fmt.Println(s2)
	fmt.Println(arr)

	fmt.Println("After updateSlice(s1)")
	updateSlice(s2)
	fmt.Println(s1)
	fmt.Println(s2)
	fmt.Println(arr)

	fmt.Println("Reslice")
	fmt.Println(s2)          // [100 1 100 3 4 5 6 7]
	fmt.Println(s2[2:5])     // [100 3 4]
	fmt.Println(s2[2:5][1:]) // [3 4]

	// slice的原理：由 ptr, len, cap三部分组成
	// ptr是指向开头的元素
	// len是长度
	// cap是ptr指向的元素到原数组最后一个元素之间的长度
	// slice可以向后扩展，不能向前扩展
	// s[i]的i不可以超过len(s)，向后扩展不可以超过底层数组caps(s)
	fmt.Println("Extending slice")
	fmt.Printf("s2[2:5]=%v, len(s2[2:5])=%d, cap(s2[2:5])=%d", s2[2:5], len(s2[2:5]), cap(s2[2:5]))
	s3 := s2[2:5][3:5]
	fmt.Println(s3) // [5 6]
	//fmt.Println(s2[:5][5:9])
	// 添加元素时如果超过cap，系统会重新分配更大的底层数组
	s4 := append(s3, 10)
	s5 := append(s4, 11)
	s6 := append(s5, 12)
	fmt.Printf("s6=%v, len(s6])=%d, cap(s6)=%d, s6[:6]=%v\n", s6, len(s6), cap(s6), s6[:6])
	fmt.Println(arr)

}

func printSlice(s []int) {
	fmt.Printf("s=%v len=%d, cap=%d\n", s, len(s), cap(s))
}

func test2() {
	// 数组动态扩容的过程中长度会随着元素的逐渐加1，容量到达2的n次方的时候会翻倍
	/*var s []int // Zero value for slice is nil
	for i := 0; i < 100; i++ {
		printSlice(s)
		s = append(s, 2*i+1)
	}
	fmt.Println(s)*/

	fmt.Println("创建slice")
	s1 := []int{2, 4, 6, 8, 10}
	printSlice(s1)

	s2 := make([]int, 16)
	printSlice(s2)

	s3 := make([]int, 16, 32)
	printSlice(s3)

	fmt.Println("复制slice")
	copy(s2, s1)
	printSlice(s2)

	fmt.Println("从slice中删除元素")
	// 从s2中删除下标为3的元素
	s2 = append(s2[:3], s2[4:]...)
	printSlice(s2)

	s4 := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
	printSlice(s4)
	s2 = append(s4[:3], s4[4:]...)
	printSlice(s2)

	// 删除并获取头尾元素
	head := s2[0]
	s2 = s2[1:]
	tail := s2[len(s2)-1]
	s2 = s2[:len(s2)-1]
	fmt.Println(head, tail)
	printSlice(s2)
}

func main() {
	//test1()
	test2()
}
